filterJson = (function( config ) {
	var filterJsonLoop = function(json, property, wrapper, value) {
			if(!property) {
				var errorMsg = 'The argument: property has to be passed.';
				if(window.console) {
					console.error ? console.error( errorMsg ) : console.log( errorMsg );
				}
				else {
					alert( errorMsg );
				}
				return;
			}
			if(json && typeof json == 'object') {
				for(key in json) {
					//if(property === key) {
					if(propertyKeyMatch(key)) {
						var constructReturnObject = function(wrapperValue, plainValue) {
								ret.filteredJson.push(wrapper ? wrapperValue : plainValue);
							};
							
						if(value && value != '') {
							var type = Object.prototype.toString.call( json[key] ),
								innerComparo = function(type, originalValue, valueToCompare) {
									if(type === "[object String]") {
										var originalValueLowerCase = originalValue.toLowerCase(),
											valueToCompareLowerCase = valueToCompare.toLowerCase();
										
										if(!matchCase) {
											if(originalValueLowerCase == valueToCompareLowerCase || (checkContains && originalValueLowerCase.indexOf(valueToCompareLowerCase) != -1)) {
												constructReturnObject(json, originalValue);
											}
										}
										else {
											if(originalValue == valueToCompare || (checkContains && originalValue.indexOf(valueToCompare) != -1)) {
												constructReturnObject(json, originalValue);
											}
										}
									}
									else if(type === "[object Number]") {
										if(originalValue === parseInt( valueToCompare )) {
											constructReturnObject(json, originalValue);
										}
									}
									else if(type === "[object Boolean]") {
										/*
											Note:
											Boolean(anyString other than blankString) is true
											Boolean(anyNumber, even negative number but other than 0) is true
											Boolean(true) is true abd Boolean(false) is false
										*/
										var booleanvalueToCompare = false;
										if(Object.prototype.toString.call( valueToCompare ) === "[object String]") {
											if(valueToCompare.toLowerCase() == "true") {
												booleanvalueToCompare = true;
											}
										}
										if(originalValue === booleanvalueToCompare) {
											constructReturnObject(json, originalValue);
										}
									}
									else if(type === "[object Array]") {
										if(originalValue.length > 0) {
											for(k in originalValue) {
												innerComparo(Object.prototype.toString.call( originalValue[k] ), originalValue[k], valueToCompare);
											}
										}
									}
									else if(type === "[object Object]") {
										filterJsonLoop(originalValue, property, wrapper, valueToCompare);
									}
								};
							
							innerComparo(type, json[key], value);
						}
						else {
							constructReturnObject(json, json[key]);
						}
					}
					filterJsonLoop(json[key], property, wrapper, value);
				}
			}
			return ret;
		},
		propertyKeyMatch = function(key) {
			if(config.property && Object.prototype.toString.call( config.property ) === "[object Array]") {
				var flag = false;
				for(var index = 0; index < config.property.length; index++) {
					if(config.property[index] === key) {
						flag = true;
						break;
					}
				}
				return flag;
			}
			return (config.property === key);
		},
		ret = {filteredJson: []};
		checkContains = config.checkContains ? config.checkContains : false,
		matchCase = config.matchCase ? config.matchCase : false,
		returnObject = filterJsonLoop(config.json, config.property, config.wrapper, config.value),
		filteredJson = null;
		
		if(returnObject && returnObject.filteredJson) {
			filteredJson = returnObject.filteredJson.length > 0 ? returnObject.filteredJson : returnObject.filteredJson[0];
		}
		
	return filteredJson;
});